package waskung

import (
	"fmt"
	"strings"

	"golang.org/x/net/html"
)

// A TagBrush represents an HTML element that is in the process of being
// generated.
type TagBrush struct {
	tag  string
	attr []html.Attribute
	w    *HTMLWriter
}

// Tag adds a new HTML element.
func (h *HTMLWriter) Tag(tagName string) *TagBrush {
	h.clearPending()
	h.pending = &TagBrush{
		tag: tagName,
		w:   h,
	}
	return h.pending
}

// Attr adds an attribute to t.
func (t *TagBrush) Attr(key, val string) *TagBrush {
	t.attr = append(t.attr, html.Attribute{
		Key: key,
		Val: val,
	})
	return t
}

// With executes f in the context of t: it outputs t's start tag, then executes
// f, then outputs t's closing tag.
func (t *TagBrush) With(f func()) {
	if voidElements[t.tag] {
		t.w.Error(fmt.Errorf("With() called on a void element (<%s>)", t.tag))
		return
	}
	t.w.pending = nil

	t.w.WriteToken(html.Token{
		Type: html.StartTagToken,
		Data: t.tag,
		Attr: t.attr,
	})

	f()

	t.w.WriteToken(html.Token{
		Type: html.EndTagToken,
		Data: t.tag,
	})
}

// Text sets t's contents to the text s.
func (t *TagBrush) Text(s string) {
	if voidElements[t.tag] {
		t.w.Error(fmt.Errorf("Text() called on a void element (<%s>)", t.tag))
		return
	}
	t.w.pending = nil

	if !strings.Contains(s, "\n") || t.tag == "textarea" || t.tag == "pre" {
		t.w.openAndClose(html.Token{
			Type: html.StartTagToken,
			Data: t.tag,
			Attr: t.attr,
		}, s)
		return
	}

	t.With(func() {
		t.w.Text(s)
	})
}
